1. Technical Field
The present invention relates to techniques for program transformation, and more particularly, to program transformation techniques which facilitate program analysis.
2. Description of the Related Art
Modern object-oriented programming languages (e.g., C++) provide abstraction and data encapsulation features such as multiple class inheritance, dynamic virtual function dispatch, overloading, constructors and destructors, templates, functors, standard libraries, etc. Although these features may be helpful to a software developer during the creation of a program, these features complicate subsequent analysis of the program (e.g., program testing, program verification, bug testing, model checking, etc.).
When dealing with C++ programs, conventional analysis techniques have proved ineffective. These techniques typically perform analysis by translating the C++ program into C (often referred to as “lowering of a C++ program”), and performing analysis on the lowered program. However, traditional lowering techniques translate the program in a manner which is optimized for run-time performance and small memory footprint, as opposed to program analysis. Consequently, the translated program utilizes complex pointer arithmetic operations, virtual-base offsets, virtual function pointer tables, and run-time libraries. Unfortunately, program analysis and testing procedures do not perform well in the presence of these “analysis-hindering features.”
One reason why the translated programs include the analysis-hindering features, such as virtual function pointer tables, is to account for the use of multiple class inheritance in the original program. “Multiple class inheritance” or “multiple inheritance” refers to a feature in a programming language which permits a class, or an object defined by a class, to inherit behaviors and features from more than one superclass or parent class. Other features of the original program that contribute to the use of these analysis-hindering features include complex expressions in the original program and implicit expressions in the original program (e.g., implicit calls to constructors and deconstructors, implicit overloaded operator calls, etc.).